﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EvoAlgLib;


namespace Experiment
{
    class Program
    {
        static void Main(string[] args)
        {
            int repetitions = 10;
            String expsufix = DateTime.Now.ToString("yyyy-MM-dd-HH-mm");
            TextWriter outfile = new StreamWriter("..\\..\\output-" + expsufix + ".csv");
            Individual superbest = null;
            for (int rep = 0; rep < repetitions; rep++)
            {

                LibStatics.setRandomizer(new Random());
                GenArrayIndividual.setLength(29);

                // init parameters

                int popsize = 1000;
                double p_mutate = 0.7;
                double p_crossover = 0.1;
                int generations = 30;

                IndFactory factory = new TSPFactory();
                factory.setPMutate(p_mutate);

                Crossover crosser = new OrderCrossover(p_crossover, factory);

                Selector selector = new BakerSUSSelector(1);


                // create inital population (random)
                List<Individual> pop = new List<Individual>();
                while (pop.Count < popsize)
                {
                    pop.Add(factory.getIndividual());
                }


                // start evolution
                for (int gen = 0; gen < generations; gen++)
                {

                    // compute statistics
                    Individual best = null;
                    double avg = 0;
                    foreach (Individual ind in pop)
                    {
                        if (best == null || ind.getFitness() > best.getFitness())
                        {
                            best = ind;
                            if (superbest == null || best.getFitness() > superbest.getFitness())
                                superbest = best;
                        }
                        avg += ind.getFitness();
                    }
                    avg /= pop.Count();

                    // display stats

                    Console.Out.WriteLine(gen + ", " + best.getFitness() + ", " + avg);
                    Console.Out.WriteLine("Best: " + best.ToString() + " - " + (1.0 / best.getFitness()).ToString());
                    outfile.WriteLine(rep+", "+gen + ", " + 1.0/best.getFitness() + ", " + 1.0/avg);

                    // create next generation
                    List<Individual> newgen = new List<Individual>();
                    selector.resetTable(pop);
                    for (int i = 0; i < popsize / 2; ++i)
                    {
                        List<Individual> parents = selector.select();
                        foreach (Individual ind in crosser.cross(parents))
                            newgen.Add(ind);
                    }
                    pop = newgen;
                }
            }
            outfile.Close();
            Console.Out.WriteLine("SuperBest: " + superbest.ToString() + " - " + (1.0 / superbest.getFitness()).ToString());
        }
    }
}
